﻿///
/// @file PlatformArm64.h
/// @brief  ARM64平台相关头文件
/// @author shentl
/// @version 2.0
/// @date 2025-04-28
///
/// @copyright Copyright (c) 2025
///
/// @par 修改日志:
/// <table>
/// <tr><th>Date       <th>Version <th>Author  <th>Description
/// <tr><td>2025-04-28 <td>2.0     <td>shentl  <td>调整为真正64位平台描述
/// </table>
///
#pragma once

#include <string>
#include "RegVariable.h"

// 在操作过程中临时借助的寄存器为ARM64_TMP_REG_NO
#define ARM64_TMP_REG_NO 9 // 通常选x9作为临时寄存器

// 栈寄存器SP和帧指针FP
#define ARM64_SP_REG_NO 31 // SP寄存器编号为31
#define ARM64_FP_REG_NO 29 // FP(Frame Pointer)是x29

// 函数返回地址寄存器(LR)
#define ARM64_LR_REG_NO 30 // Link Register是x30

// 零寄存器WZR/XZR
#define ARM64_ZR_REG_NO 32 // 零寄存器编号为32（不在通用寄存器范围内）

/// @brief ARM64平台信息
class PlatformArm64 {

    /// @brief 循环左移两位
    /// @param num
    static void roundLeftShiftTwoBit(unsigned int & num);

    /// @brief 判断num是否是常数表达式，8位数字循环右移偶数位得到
    /// @param num
    /// @return
    static bool __constExpr(int num);

public:
    /// @brief 同时处理正数和负数
    /// @param num
    /// @return
    static bool constExpr(int num);

    /// @brief 判定是否是合法的偏移
    /// @param num
    /// @return
    static bool isDisp(int num);

    /// @brief 判断是否是合法的寄存器名
    /// @param name 寄存器名字
    /// @return 是否是
    static bool isReg(std::string name);

    /// @brief 最大寄存器数目（包括零寄存器）
    static const int maxRegNum = 33; // x0-x30, sp, wzr

    /// @brief 可使用的通用寄存器的个数（通常保留x29(fp)、x30(lr)、x31(sp)，前28个常用）
    static const int maxUsableRegNum = 28; // x0-x27（通常 x28-x31 特殊用途）
    static const int maxUsableFloatNum = 32; // s0-s31

    /// @brief 寄存器的名字，x0-x30, sp
    static const std::string regName[maxRegNum];

    static const std::string regNameW[maxRegNum];

    // 新增：浮点数寄存器支持
    static const std::string regNameS[maxRegNum]; // s0-s31
    static RegVariable * floatRegVal[PlatformArm64::maxRegNum];

    // 新增：将64位寄存器名(x0-x30)转换为32位形式(w0-w30)
    static std::string toWReg(const std::string & xreg);

    /// @brief 对寄存器分配Value，记录位置
    static RegVariable * intRegVal[PlatformArm64::maxRegNum];

    /// @brief 获取零寄存器名称（根据目标寄存器名自动选择wzr/xzr）
    /// @param regName 目标寄存器名
    /// @return 零寄存器名称
    static std::string getZeroRegName(const std::string & regName);
};
